package edu.osu.cse.c651.cryptochess;

import java.util.ArrayList;

import android.util.Log;

/**
 * The chess board, populated with pieces. This data alone is passed between
 * players. It is the model.
 * 
 * @author Team Pawned
 * 
 */
public class ChessBoard {

	/**
	 * The length (and width) of the board
	 */
	private final int boardLength = 8;

	/**
	 * The chess board representation
	 */
	private final Piece[][] chessBoard = new Piece[boardLength][boardLength];

	/**
	 * Set to true if White is in check
	 */
	private boolean check_WHITE;

	/**
	 * Set to true if Black is in check
	 */
	private boolean check_BLACK;

	/**
	 * Holds the Piece captured on the last move executed (null if no Piece was
	 * captured on the last move)
	 */
	private Piece currentCapturedPiece;

	/**
	 * The color (White or Black) in check
	 */
	private Color inCheck;

	/**
	 * Used by the executeMove method to ensure that the move method, which
	 * checks the legality of a move, was invoked beforehand
	 */
	private boolean legalMove;

	/**
	 * Set to true if castling has just occured. Used to notify executeMove to
	 * do nothing, because Piece movement is handled by move in this case.
	 */
	private boolean castled;

	/**
	 * True if the end of the game has been reached
	 */
	private boolean endGame;

	/**
	 * True if a pawn has just reached the opposing end of the board (in which
	 * case a captured piece may be reinstated)
	 */
	private boolean pawnReachedEnd;

	/**
	 * The row of the pawn that has just reached the opposing end of the board
	 */
	private int plx = 0;

	/**
	 * The column of the pawn that has just reached the opposing end of the
	 * board
	 */
	private int ply = 0;

	/**
	 * The state of the match
	 */
	private Winner winner;

	/**
	 * Used for debugging
	 */
	public static String TAG = "ChessBoard";

	// private ArrayList<Coordinate> enemyPieceCoords;

	/**
	 * ChessBoard constructor. Populates the board with pieces.
	 */
	public ChessBoard() {
		currentCapturedPiece = null;
		inCheck = null;
		legalMove = false;
		castled = false;
		endGame = false;
		winner = Winner.GAME_IN_PROGRESS;
		pawnReachedEnd = false;
		plx = 0;
		ply = 0;
		populate();
	}

	/**
	 * Returns true if the supplied movement, from one grid square to another,
	 * is legal according to the Piece, board and player color.
	 * 
	 * @param playerColor
	 *            White or Black
	 * @param x1
	 *            row of the starting grid square
	 * @param y1
	 *            column of the starting grid square
	 * @param x2
	 *            row of the ending grid square
	 * @param y2
	 *            column of the ending grid square
	 * @returns boolean true if this movement is legal
	 */
	public boolean move(Color playerColor, int x1, int y1, int x2, int y2) {
		if (!legalLoc(x1) || !legalLoc(x2) || !legalLoc(y1) || !legalLoc(y2)) {
			return false;
		}

		Log.d(TAG, "Legal location");
		// enemyPieceCoords.clear();

		// Check that FromLoc has a piece
		if (chessBoard[x1][y1] == null) {
			// System.err.println("\n1");
			return false;
		} else if (chessBoard[x1][y1].color() != playerColor) {
			// System.err.println("\n2");
			return false;
		}

		// Check that ToLoc doesn't have a Piece of the same Color
		if (chessBoard[x2][y2] != null) {
			if (chessBoard[x2][y2].color() == chessBoard[x1][y1].color()) {
				// System.err.println("\n3");
				Log.d(TAG, "Can't move onto a like-colored player");
				return false;
			}
		}

		// Check that the movement is valid for the Piece
		legalMove = true;
		boolean pawnFlag = false;
		if (!chessBoard[x1][y1].legalMove(x1, y1, x2, y2)) {
			legalMove = false;
			Log.d(TAG, "Illegal move");
			if (isPawn(chessBoard[x1][y1])) {
				Log.d(TAG, "Illegal Pawn move");
				pawnFlag = true;
			}
		}

		if (!pawnFlag && isPawn(chessBoard[x1][y1])) {
			if (chessBoard[x2][y2] != null) {
				Log.d(TAG,
						"Pawn cannot take enemy piece directly across from it");
				return false;
			}
		}

		// Does this piece hop another piece? (Illegal if not a Knight)
		if (hopCheck(x1, y1, x2, y2)) {
			Log.d(TAG, "Can't hop another piece");
			return false;
		}

		/* Special situations */
		// Attacking pawn? Pawn double-hop?
		if (pawnFlag) {
			Log.d(TAG, "Pawn flag");
			if (isPawnAttackMove(chessBoard[x1][y1].color(), x1, y1, x2, y2)
					|| isPawnDoubleHop(chessBoard[x1][y1].color(), x1, y1, x2,
							y2)) {
				Log.d(TAG, "Irregular pawn move = true");
				legalMove = true;
			}
		}

		if (isPawn(chessBoard[x1][y1]) && legalMove) {
			if (chessBoard[x1][y1].color() == Color.WHITE) {
				if (x1 == 6) {
					pawnReachedEnd = true;
					plx = x2;
				}
			} else {
				if (x1 == 1) {
					pawnReachedEnd = true;
					ply = y2;
				}
			}
		}

		// Castling?
		if (castling(chessBoard[x1][y1].color(), x1, y1, x2, y2)) {
			castled = true;
			Log.d(TAG, "castling = true");
			return true; // if it is castling, board changes will occur
			// in the private method
		}

		if (!legalMove) {
			Log.d(TAG, "Final illegal move");
			return false;
		}

		// Do fake move before calling in check
		Piece swapPiece = this.chessBoard[x2][y2];
		this.chessBoard[x2][y2] = this.chessBoard[x1][y1];
		this.chessBoard[x1][y1] = null;
		
		Coordinate king = findKing(Color.WHITE, this);
		// Checks game status for either checkmate or stalemate
		Status gameStatus = inMate(playerColor, this, king.x, king.y);
		if (gameStatus == Status.CHECKMATE) {
			endGame = true;
			winner = Winner.BLACK; 
		} else if (gameStatus == Status.STALEMATE) {
			endGame = true;
			winner = Winner.STALEMATE;
		}
		
		
		king = findKing(Color.BLACK, this);
		// Checks game status for either checkmate or stalemate
		gameStatus = inMate(Color.BLACK, this, king.x, king.y);
		if (gameStatus == Status.CHECKMATE) {
			endGame = true;
			winner = Winner.BLACK;
		} else if (gameStatus == Status.STALEMATE) {
			endGame = true;
			winner = Winner.STALEMATE;
		}
		
		// Did this player just move himself into check? If so, return false
		king = findKing(playerColor, this);
		if (inCheck(playerColor, this, king.x, king.y)) {
			// Revert the fake move before moving on
			this.chessBoard[x1][y1] = this.chessBoard[x2][y2];
			this.chessBoard[x2][y2] = swapPiece;
			return false;
		}
		this.chessBoard[x1][y1] = this.chessBoard[x2][y2];
		this.chessBoard[x2][y2] = swapPiece;

		Log.d(TAG, "Legal move");
		legalMove = true;
		return true;
	}

	/**
	 * Returns true if the Piece selected is of the same color as this Player,
	 * and false if it is not the same color or if a piece was not selected
	 * 
	 * @param player
	 *            the color of this player
	 * @param x1
	 *            the row of the board from which the Piece will be moved
	 * @param y1
	 *            the column of the board from which the Piece will be moved
	 * @return boolean true if the square indicated contains a Piece of a color
	 *         that matches this player
	 */
	public boolean correctPlayerSelected(Color player, int x1, int y1) {
		if (chessBoard[x1][y1] != null) {
			if (chessBoard[x1][y1].color() == player) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Returns true if the game is over (check-mate or stalemate)
	 * 
	 * @return boolean true if the game is over
	 */
	public boolean endGame() {
		return endGame;
	}

	/**
	 * Returns the status of this game (see Winner enum)
	 * 
	 * @return Winner the status of this game
	 */
	public Winner winner() {
		return winner;
	}

	public void printBoard() {
		
	}
	
	/**
	 * Executes a movement. The Piece at (x1,y1) is moved to (x2,y2). The move
	 * method (above) MUST be called and return to true in order for this method
	 * to be invoked.
	 * 
	 * @param x1
	 *            row of the starting grid square
	 * @param y1
	 *            column of the starting grid square
	 * @param x2
	 *            row of the ending grid square
	 * @param y2
	 *            column of the ending grid square
	 */
	public void executeMove(int x1, int y1, int x2, int y2) throws Exception {

		if (!legalMove) {
			Log.d(TAG, "Illegal execute move");
			throw new Exception(
					"The legality of a move needs to be ensured before it is executed");
		}

		if (castled) {
			return;
		}

		currentCapturedPiece = chessBoard[x2][y2];

		chessBoard[x2][y2] = chessBoard[x1][y1];
		chessBoard[x2][y2].movesPlusOne();
		chessBoard[x1][y1] = null;

		legalMove = false;
		castled = false;
	}

	/**
	 * Returns the Piece captured on the most recent move
	 * 
	 * @returns Piece the Piece captured on the most recent move; null if no
	 *          Piece was captured
	 */
	public Piece getCapturedPiece() {
		return currentCapturedPiece;
	}

	/**
	 * Returns the piece at the queried location on the board
	 * 
	 * @param x
	 *            row
	 * @param y
	 *            column
	 * @return Piece null if the square is empty
	 */
	public Piece getPiece(int x, int y) {
		if (x >= 8 || x < 0 || y >= 8 || y < 0)
			return null;
		return chessBoard[x][y];
	}

	/**
	 * Populates the ChessBoard with White and Black pieces. Called by the
	 * constructor
	 */
	private void populate() {

		for (int y = 0; y < boardLength; y++) {
			chessBoard[1][y] = new Pawn(Color.WHITE);
			chessBoard[6][y] = new Pawn(Color.BLACK);
		}

		chessBoard[0][0] = new Rook(Color.WHITE);
		chessBoard[0][1] = new Knight(Color.WHITE);
		chessBoard[0][2] = new Bishop(Color.WHITE);
		chessBoard[0][3] = new Queen(Color.WHITE);
		chessBoard[0][4] = new King(Color.WHITE);
		chessBoard[0][5] = new Bishop(Color.WHITE);
		chessBoard[0][6] = new Knight(Color.WHITE);
		chessBoard[0][7] = new Rook(Color.WHITE);

		chessBoard[7][0] = new Rook(Color.BLACK);
		chessBoard[7][1] = new Knight(Color.BLACK);
		chessBoard[7][2] = new Bishop(Color.BLACK);
		chessBoard[7][3] = new Queen(Color.BLACK);
		chessBoard[7][4] = new King(Color.BLACK);
		chessBoard[7][5] = new Bishop(Color.BLACK);
		chessBoard[7][6] = new Knight(Color.BLACK);
		chessBoard[7][7] = new Rook(Color.BLACK);
	}

	/**
	 * Returns true if x is greater than or equal to zero, and less than the
	 * length of the board. Used in determining movement legality
	 * 
	 * @param x
	 *            row or column number
	 * @returns boolean true if >=0 and <=7
	 */
	private boolean legalLoc(int x) {
		return (x >= 0 && x < boardLength);
	}

	/**
	 * Returns true if a Piece, other than a Knight, hops another Piece (which
	 * is illegal) in route to its destination grid square. Used in determing
	 * movement legality.
	 * 
	 * @param x1
	 *            row of the starting grid square
	 * @param y1
	 *            column of the starting grid square
	 * @param x2
	 *            row of the ending grid square
	 * @param y2
	 *            column of the ending grid square
	 * 
	 * @returns boolean true if a non-Knight piece hops another Piece in route
	 *          to its destination
	 */
	private boolean hopCheck(int x1, int y1, int x2, int y2) {
		if (chessBoard[x1][y1].name() == PieceName.Knight) {
			return false;
		}
		int deltaX = (x2 - x1) / (Math.max(Math.abs(x1 - x2), 1));
		int deltaY = (y2 - y1) / (Math.max(Math.abs(y1 - y2), 1));
		int c = 1;
		while (c < Math.max(Math.abs(x1 - x2), Math.abs(y1 - y2))) {
			if (legalLoc(x1 + deltaX * c) && legalLoc(y1 + deltaY * c)) {
				if (chessBoard[x1 + deltaX * c][y1 + deltaY * c] != null) {
					return true;
				}
			}
			c += 1;
		}
		return false;
	}

	/**
	 * Returns true if the supplied piece is a Pawn
	 * 
	 * @param piece
	 *            the piece to be tested
	 * @return boolean true if the Piece is a Pawn
	 */
	private boolean isPawn(Piece piece) {
		return piece.name() == PieceName.Pawn;
	}

	/**
	 * Returns true if the movement described with the supplied parameters is a
	 * legal double-hop by a Pawn. Used by the move method to determine if a
	 * move is legal.
	 * 
	 * @param c
	 *            the Color of this plater
	 * @param x1
	 *            the row of the square from which a Piece will be moved
	 * @param y1
	 *            the column of the square from which a Piece will be moved
	 * @param x2
	 *            the row of the square to which a Piece will be moved
	 * @param y2
	 *            the column of the square to which a Piece will be moved
	 * @return boolean true if the movement is a double-hop by a Pawn
	 */
	private boolean isPawnDoubleHop(Color c, int x1, int y1, int x2, int y2) {
		if (c == Color.WHITE) {
			if ((x1 == 1) && (x2 == 3) && (y2 == y1)) {
				return true;
			}
		} else {
			if ((x1 == 6) && (x2 == 4) && (y2 == y1)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Returns true if the movement described by the supplied parameters is a
	 * pawn attack move, where it moves diagonally to take out an opponent. Used
	 * in the move method to determine move legality
	 * 
	 * @param c
	 *            Color the color of the Pawn being moved
	 * @param x1
	 *            int the row of the square from which the Pawn is being moved
	 * @param y1
	 *            int the column of the square from which the Pawn is being
	 *            moved
	 * @param x2
	 *            int the row of the square to which the Pawn is being moved
	 * @param y2
	 *            int the column of the square to which the Pawn is being moved
	 * @return boolean true if this movement is a Pawn attack movement
	 */
	private boolean isPawnAttackMove(Color c, int x1, int y1, int x2, int y2) {
		boolean valid = false;
		if (c == Color.WHITE) {
			if (chessBoard[x2][y2] == null) {
				return false;
			}
			if (((y2 == (y1 + 1)) || (y2 == (y1 - 1))) && (x2 == (x1 + 1))
					&& (chessBoard[x2][y2].color() == Color.BLACK)) {
				valid = true;
			} else {
				valid = false;
			}
		} else {
			if (chessBoard[x2][y2] == null) {
				return false;
			}
			if (((y2 == (y1 + 1)) || (y2 == (y1 - 1))) && (x2 == (x1 - 1))
					&& (chessBoard[x2][y2].color() == Color.WHITE)) {
				valid = true;
			} else {
				valid = false;
			}
		}
		return valid;
	}

	/**
	 * This method returns true if a Pawn has just reached the end of the Board
	 * 
	 * @return boolean true if a Pawn has reached the end of the board
	 */
	public boolean pawnReachedEnd() {
		return pawnReachedEnd;
	}

	/**
	 * If a Pawn has reached the opposing end of the board, this method returns
	 * the row of the square where it sits.
	 * 
	 * @return int the row of the square where the arrived Pawn sits
	 */
	public int arrivedPawnX() {
		return plx;
	}

	/**
	 * If a Pawn has reached the opposing end of the board, this method returns
	 * the column of the square where it sits.
	 * 
	 * @return int the column of the square where the arrived Pawn sits
	 */
	public int arrivedPawnY() {
		return ply;
	}

	/**
	 * Used to switch out a Piece with a Pawn that has reached the opposing end
	 * 
	 * @param piece
	 *            the Piece to be switched out
	 * @param x
	 *            the row of the square to where the Piece will be switched in
	 * @param y
	 *            the column of the square to where the Piece will be switched
	 *            in
	 */
	public void pawnReachedEnd_SwitchInPiece(Piece piece, int x, int y) {
		chessBoard[x][y] = piece;
		pawnReachedEnd = false;
	}

	/**
	 * Returns true if the move described with the supplied parameters indicates
	 * a special castling movement
	 * 
	 * @param c
	 *            the Color of the Player who is moving
	 * @param x1
	 *            starting row
	 * @param y1
	 *            starting column
	 * @param x2
	 *            ending row
	 * @param y2
	 *            ending column
	 * @return boolean true if the movement is a castling movement
	 */
	private boolean castling(Color c, int x1, int y1, int x2, int y2) {
		boolean valid = false;
		if (c == Color.WHITE) {
			if ((x1 == 0) && (y1 == 4)) {
				if ((x2 == 0) && (y2 == 2)) {
					if (chessBoard[0][1] == null && chessBoard[0][2] == null
							&& chessBoard[0][3] == null) {
						if (chessBoard[0][0].getClass().getName()
								.equals("Rook")
								&& chessBoard[0][4].getClass().getName()
										.equals("King")) {
							if (chessBoard[0][0].moveCount() == 0
									&& chessBoard[0][4].moveCount() == 0) {
								chessBoard[0][2] = chessBoard[0][4];
								chessBoard[0][4] = null;
								chessBoard[0][3] = chessBoard[0][0];
								chessBoard[0][0] = null;
								chessBoard[0][2].movesPlusOne();
								chessBoard[0][3].movesPlusOne();
								currentCapturedPiece = null;
								return true;
							}
						}
					}
				} else if ((x2 == 0) && (y2 == 6)) {
					if (chessBoard[0][5] == null && chessBoard[0][6] == null) {
						if (chessBoard[0][7].getClass().getName()
								.equals("Rook")
								&& chessBoard[0][4].getClass().getName()
										.equals("King")) {
							if (chessBoard[0][7].moveCount() == 0
									&& chessBoard[0][4].moveCount() == 0) {
								chessBoard[0][6] = chessBoard[0][4];
								chessBoard[0][4] = null;
								chessBoard[0][5] = chessBoard[0][7];
								chessBoard[0][7] = null;
								chessBoard[0][6].movesPlusOne();
								chessBoard[0][5].movesPlusOne();
								currentCapturedPiece = null;
								return true;
							}
						}
					}
				}
			}
		} else {
			if ((x1 == 7) && (y1 == 4)) {
				if ((x2 == 7) && (y2 == 2)) {
					if (chessBoard[7][1] == null && chessBoard[7][2] == null
							&& chessBoard[7][3] == null) {
						if (chessBoard[7][0].getClass().getName()
								.equals("Rook")
								&& chessBoard[7][4].getClass().getName()
										.equals("King")) {
							if (chessBoard[7][0].moveCount() == 0
									&& chessBoard[7][4].moveCount() == 0) {
								chessBoard[7][2] = chessBoard[7][4];
								chessBoard[7][4] = null;
								chessBoard[7][3] = chessBoard[7][0];
								chessBoard[7][0] = null;
								chessBoard[7][2].movesPlusOne();
								chessBoard[7][3].movesPlusOne();
								currentCapturedPiece = null;
								return true;
							}
						}
					}
				} else if ((x2 == 7) && (y2 == 6)) {
					if (chessBoard[7][5] == null && chessBoard[7][6] == null) {
						if (chessBoard[7][7].getClass().getName()
								.equals("Rook")
								&& chessBoard[7][4].getClass().getName()
										.equals("King")) {
							if (chessBoard[7][7].moveCount() == 0
									&& chessBoard[7][4].moveCount() == 0) {
								chessBoard[7][6] = chessBoard[7][4];
								chessBoard[7][4] = null;
								chessBoard[7][5] = chessBoard[7][7];
								chessBoard[7][7] = null;
								chessBoard[7][6].movesPlusOne();
								chessBoard[7][5].movesPlusOne();
								currentCapturedPiece = null;
								return true;
							}
						}
					}
				}
			}
		}
		return false;
	}

	/**
	 * Returns true if the King at location (x,y) is in check
	 * 
	 * @param color
	 *            the Color of the King
	 * @param board
	 *            this ChessBoard
	 * @param x
	 *            the row of the square where the King sits
	 * @param y
	 *            the column of the square where the King sits
	 * @return boolean true if the King is in check
	 */
	public static boolean inCheck(Color color, ChessBoard board, int x, int y) {
		// Loops through all spaces on the board
		for (int i = 0; i < 8; i++) {
			for (int j = 0; j < 8; j++) {
				// if an enemy piece has a possible move with the coordinates of
				// the king, the king is in check
				if (board.getPiece(i, j) != null
						&& board.getPiece(i, j).color() != color) {
					ArrayList<Coordinate> moves = board.getPiece(i, j)
							.possibleMoves(board, i, j);
					for (int k = 0; k < moves.size(); k++) {
						if (moves.get(k).x == x && moves.get(k).y == y)
							return true;
					}
				}
			}
		}

		// Not in check
		return false;
	}

	/**
	 * Returns a status regarding this Player and whether he is in check-mate
	 * 
	 * @param color
	 *            the color of this player
	 * @param board
	 *            this ChessBoard
	 * @param x
	 *            the row of the square where the King sits
	 * @param y
	 *            the column of the square where the King sits
	 * @return Status NO_MATE, CHECKMATE, or STALEMATE
	 */
	public static Status inMate(Color color, ChessBoard board, int x, int y) {
		// Loops through all spaces on the board
		for (int i = 0; i < 8; i++) {
			for (int j = 0; j < 8; j++) {
				// If a friendly piece can move without the king being in check,
				// then its not mate.
				if (board.getPiece(i, j) != null
						&& board.getPiece(i, j).color() == color
						&& board.getPiece(i, j).name() != PieceName.King) {
					ArrayList<Coordinate> moves = board.getPiece(i, j)
							.possibleMoves(board, x, y);
					for (int h = 0; h < moves.size(); h++) {
						Coordinate move = moves.get(h);
						// Do fake move before calling in check
						Piece swapPiece = board.chessBoard[move.x][move.y];
						board.chessBoard[move.x][move.y] = board.chessBoard[i][j];
						board.chessBoard[i][j] = null;

						// if not in check, then at least one move works, so no
						// mate yet
						boolean check = inCheck(color, board, x, y);

						// Revert the fake move before moving on
						board.chessBoard[i][j] = board.chessBoard[move.x][move.y];
						board.chessBoard[move.x][move.y] = swapPiece;
						if (!check)
							return Status.NO_MATE;
					}
				}
				// its the king, so the inCheck coordinates need to be changed
				else if (board.getPiece(i, j) != null
						&& board.getPiece(i, j).color() == color) {
					ArrayList<Coordinate> moves = board.getPiece(i, j)
							.possibleMoves(board, x, y);
					for (int h = 0; h < moves.size(); h++) {
						Coordinate move = moves.get(h);
						// TODO: actually do move before calling in check
						// Do fake move before calling in check
						Piece swapPiece = board.chessBoard[move.x][move.y];
						board.chessBoard[move.x][move.y] = board.chessBoard[x][y];
						board.chessBoard[x][y] = null;

						// if not in check, then at least one move works, so no
						// mate yet
						boolean check = inCheck(color, board, move.x, move.y);

						// Revert the fake move before moving on
						board.chessBoard[x][y] = board.chessBoard[move.x][move.y];
						board.chessBoard[i][j] = swapPiece;

						if (!check) {
							return Status.NO_MATE;
						}
					}
				}
			}
		}

		// Game is over one way or another
		if (inCheck(color, board, x, y))
			return Status.CHECKMATE;
		else
			return Status.STALEMATE;
	}

	/**
	 * Finds the coordinates of the King on the chess board
	 * 
	 * @param color
	 *            the color of the King
	 * @param board
	 *            this ChessBoard
	 * @return Coordinate an x,y pair
	 */
	public static Coordinate findKing(Color color, ChessBoard board) {
		int i = 0;
		int j = 0;

		// Loops through all spaces on the board
		while (i < 8) {
			j = 0;
			while (j < 8) {
				if (board.getPiece(i, j) != null
						&& board.getPiece(i, j).name() == PieceName.King
						&& board.getPiece(i, j).color() == color) {
					Coordinate king = new Coordinate(i, j);
					return king;
				}
				j++;
			}
			i++;
		}
		return new Coordinate(-1, -1);
	}

	/**
	 * Sets a piece on a square of this chess board
	 * 
	 * @param piece
	 *            the Piece to be set
	 * @param x
	 *            the row of the square on the board
	 * @param y
	 *            the column of the square on the board
	 */
	public void setSquare(Piece piece, int x, int y) {
		if (piece == null)
			this.chessBoard[x][y] = null;
		else
			this.chessBoard[x][y] = piece;
	}
	public Piece[][] getBoard()
	{
		return this.chessBoard;
	}
	public void setWinner(Winner win)
	{
		this.winner = win;
	}
	public void setEndGame(boolean bool)
	{
		this.endGame = bool;
	}
}